<?php

namespace App\Models;

use App\Http\Library\Coordinate;
use App\Http\Library\Map;
use App\Services\OrderService;
use Dcat\Admin\Traits\HasDateTimeFormatter;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Facades\DB;
use hg\apidoc\annotation as Apidoc;
use Illuminate\Support\Facades\Log;
use Throwable;

/**
 * App\Models\ShopUser
 *
 * @property $id
 * @property $user_id
 * @property $username
 * @property $password
 * @property $shop_id
 * @property $avatar
 * @property mixed $text
 * @property \App\Models\User|null $user
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser query()
 * @mixin \Eloquent
 * @property string $shop_rate 门店服务每笔交易 分成比例
 * @property string $card_rate 门店服务每笔交易洗车卡打折 消费 分成比例
 * @property string $money 可用余额
 * @property string $used_money 已提现余额
 * @property float $wait_money 待结算金额
 * @property string|null $remember_token
 * @property int $status
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereAvatar($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereMoney($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser wherePassword($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereRememberToken($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereShopId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereUsedMoney($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereUserId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereUsername($value)
 * @property string $name 门店名称
 * @property string $fullname 门店负责人
 * @property string $phone 门店电话
 * @property string $address 详细地址
 * @property string $longitude 经度
 * @property string $latitude 纬度
 * @property int $agent_id 代理商ID
 * @property int $province_id 省ID
 * @property int $city_id 市ID
 * @property int $district_id 区ID
 * @property int $distance 免费接单距离限制 取消此字段
 * @property string $distance_price 超出距离限制收费(元/公里) 取消此字段
 * @property array|null $images 门店图片组
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Worker[] $workers
 * @property int|null $workers_count
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereAddress($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereCid($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereImages($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereLatitude($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereLongitude($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereName($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser wherePhone($value)
 * @property int $cid 分类ID
 * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\OrderCommission[] $commission
 * @property \App\Models\AgentUser $agent
 * @property-read int|null $commission_count
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereCityId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereDistance($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereDistancePrice($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereDistrictId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereFullname($value)
 * @method static \Illuminate\Database\Eloquent\Builder|ShopUser whereProvinceId($value)
 */
class ShopUser extends Model
{
	use HasDateTimeFormatter;
    protected $table = 'shop_users';

    protected $hidden = [
        'password'
    ];

    protected $casts = ['images'=>'json'];

    public static function booted()
    {
        self::saving(function (ShopUser $shop){
            if ($shop->isDirty("address")){
                if (!$shop->address){
                    modelError("请设置详细地址信息");
                }
            }

            $map = new Map();
            $longitude = $shop->longitude;
            $latitude = $shop->latitude;
            $address = $map->getAddress($longitude,$latitude);
            list($province_id, $city_id, $district_id) = OrderService::findAddressIds($address);
            $shop->province_id = $province_id;
            $shop->city_id = $city_id;
            $shop->district_id = $district_id;
        });
        self::created(function (ShopUser $row){
            //新增权限
            DB::table("shop_role_users")->insert([
                "role_id"=>1,"user_id"=>$row->id,'created_at'=>now()->toDateTimeLocalString(),
            ]);
        });
        self::deleting(function($row){
            DB::table("shop_role_users")->where(["role_id"=>1,"user_id"=>$row->id])->delete();
        });
    }


    public static function getOptions(){
        return self::query()->orderByDesc("id")->pluck("name","id");
    }

    public function user(){
        return $this->hasOne(User::class,"id","user_id");
    }

    public function orders(){
        return $this->hasMany(ServiceOrder::class,"shop_id","id");
    }

    public function agent(){
        return $this->hasOne(AgentUser::class,"id","agent_id");
    }

    public function workers(){
        return $this->hasMany(Worker::class,"shop_id","id");
    }

    public function commission(){
        return $this->hasMany(OrderCommission::class,"shop_id","id");
    }

    /**
     * @param int $type 类型 0=后台修改,1=订单金额,2=提现金额
     * @param int $shop_id 店铺ID
     * @param float $money 变更金额
     * @param string $remark 备注
     */
    public static function moneys(int $type, int $shop_id, float $money, string $remark){
        if ($money!=0){
            $shop = self::query()->where("id",$shop_id)->first();
            if ($shop){
                $pre_money = $shop->money;
                $after_money = $shop->money + $money;
                if ($type==2){
                    $used_money = $shop->used_money + abs($money);
                    $res = self::query()->where("id",$shop_id)->update(['money'=>$after_money,"used_money"=>$used_money]);
                }else{
                    $res = self::query()->where("id",$shop_id)->update(['money'=>$after_money]);
                }
                if ($res){
                    ShopMoney::create([
                        'type'=>$type,
                        'user_id'=>$shop->user_id,
                        'shop_id'=>$shop_id,
                        'pre_money'=>$pre_money,
                        'money'=>$money,
                        'after_money'=>$after_money,
                        'remark'=>$remark,
                    ]);
                }
            }
        }
    }

    /**
     * 计算经纬度距离
     * @param $longitude
     * @param $latitude
     * @return string
     */
    public static function getDistanceField($longitude,$latitude): string
    {
        return "(6370856*acos(cos(radians({$latitude}))*cos(radians(latitude))*cos(radians(longitude)-radians({$longitude}))+sin(radians({$latitude}))*sin(radians(latitude))))";
    }

    public static function getShops(): array
    {
        $longitude = request()->input('longitude',113.348717);
        $longitude = $longitude?:113.348717;
        $latitude = request()->input('latitude',23.02165);
        $latitude = $latitude?:23.02165;
        $distance = self::getDistanceField($longitude,$latitude);
        $limit = request()->input("limit",100);
        $limit = $limit?intval($limit):10;
        $limit = 100000;
        $list = self::query()
            ->select(["id","name","avatar","address","longitude","latitude","phone"])
            ->addSelect(DB::raw($distance . ' as distances'))
            ->withCount(["workers"])
            ->having("distances","<=",$limit*1000)
//            ->having("workers_count",">",0)
            ->where("shop_id",0)
            ->where("status","<>",2)
            ->orderBy("distances")
            ->orderByDesc("id")
            ->get();
        foreach ($list as $item){
            $distances = $item->distances;
            if ($distances>1000){
                $item->distances = number_format($distances/1000,2)."km";
            }else{
                $item->distances = number_format($distances,2)."m";
            }
            $item->avatar = cdn_url($item->avatar);
        }
        $map = new Map();
        try {
            $address = $map->getAddress($longitude,$latitude);
        } catch (Exception|Throwable $e) {
            Log::error($e->getMessage());
            $address = [];
        }
        $worker_count = collect($list)->pluck("workers_count")->sum();
        return [
            'shops'=> $list,
            'shop_count'=> count($list),
            'worker_count'=> $worker_count,
            'address'=>$address,
        ];
    }



    /**
     * @Apidoc\AddField("wait_money",type="float",default="0",desc="待结算金额")
     * @Apidoc\AddField("good_order_count",type="float",default="0",desc="待发货订单数")
     * @Apidoc\AddField("service_order_count",type="float",default="0",desc="待安排服务订单数")
     * @Apidoc\AddField("service_order_count1",type="float",default="0",desc="服务中订单数")
     * @Apidoc\AddField("service_order_count2",type="float",default="0",desc="服务已完成订单数")
     * @Apidoc\Returned(ref="App\Models\ShopUser")
     */
    public static function getDetail($user_id): ShopUser|null
    {
        $shop = self::whereUserId($user_id)->first();
        if ($shop){
            $cash_money = CashOrder::query()->where("status",0)->where("type",0)->where("shop_id",$shop->id)->sum("amount");
            $shop->money = floatval($shop->money - $cash_money);
            $shop->money = number_format($shop->money,2);
            $shop->good_order_count = GoodOrder::query()->where("state",1)
                ->where("method",1)
                ->where("shop_id",$shop->id)
                ->count();
            $shop->service_order_count = ServiceOrder::query()->where("shop_id",$shop->id)->where("worker_id",0)->where("status",0)->count();
            $shop->service_order_count1 = ServiceOrder::query()->where("shop_id",$shop->id)->where("status",1)->count();
            $shop->service_order_count2 = ServiceOrder::query()->where("shop_id",$shop->id)->whereIn("status",[2,3])->count();
            $shop->wait_money = OrderCommission::query()->where("shop_id",$shop->id)->where("is_settle",0)->sum('shop_money');
        }
        return $shop;
    }


}
